package channelService

import (
	"errors"
	"gitee.com/fierce_wolf/go-fox-edge-channel-common/channelStatus"
	"gitee.com/fierce_wolf/go-fox-edge-common/commEnv"
	"gitee.com/fierce_wolf/go-fox-edge-common/commRedisRpc"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/ChanSyncObj"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Map"
	"gitee.com/fierce_wolf/go-fox-edge-common/commUtil/Method"
	"go-fox-edge-channel-mqtt-lora/channelEntity"
	"sync"
)

type channelService struct {
	deviceEUI2Entity   sync.Map
	channelName2Entity sync.Map
}

func (e *channelService) getChannelNames() map[string]interface{} {
	result := make(map[string]interface{})
	service.channelName2Entity.Range(func(key, ctx interface{}) bool {
		result[key.(string)] = ctx
		return true
	})

	return result
}

func (e *channelService) OpenChannel(channelName string, channelParam map[string]interface{}) error {
	devEUI := Map.GetString(channelParam, "devEUI", "")
	gatewayEUI := Map.GetString(channelParam, "gatewayEUI", "")
	fPort := Map.GetInt(channelParam, "fport", 0)

	channelStatus.Param.UpdateParamStatus(channelName, "devEUI", devEUI != "")
	channelStatus.Param.UpdateParamStatus(channelName, "gatewayEUI", gatewayEUI != "")
	channelStatus.Param.UpdateParamStatus(channelName, "fport", fPort != 0)

	// 检查：参数是否为空
	if Method.HasEmpty(devEUI) {
		return errors.New("参数不能为空: devEUI")
	}

	// 创建一个内容部的LoraWanEntity实体
	loraWanEntity := &channelEntity.LoraWanEntity{}
	loraWanEntity.ChannelName = channelName
	loraWanEntity.DevEUI = devEUI
	loraWanEntity.GatewayEUI = gatewayEUI
	loraWanEntity.FPort = fPort
	e.deviceEUI2Entity.Store(devEUI, loraWanEntity)
	e.channelName2Entity.Store(channelName, loraWanEntity)

	// 为通道创建一个多线程消息交换的chan
	ChanSyncObj.Instance(devEUI)
	return nil
}

func (e *channelService) CloseChannel(channelName string, channelParam map[string]interface{}) error {
	devEUI := Map.GetString(channelParam, "devEUI", "")

	// 释放掉内部的实体
	e.channelName2Entity.Delete(channelName)
	e.deviceEUI2Entity.Delete(devEUI)

	// 释放掉为该通道创建的多线程之间消息交换的chan
	ChanSyncObj.Release(devEUI)
	return nil
}

func (e *channelService) Execute(requestVO *commRedisRpc.ChannelRequestVO) (*commRedisRpc.ChannelRespondVO, error) {
	return execute.execute(requestVO)
}
func (e *channelService) Report() ([]*commRedisRpc.ChannelRespondVO, error) {
	return report.popAll(commEnv.Service.ModelName)
}
